package nccloud.utils.riart;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * http请求工具类
 * @author wanggp
 * @date 2022年4月25日
 *
 */
public class HttpRequestUtils {

	/**
	 * get请求
	 * @param httpurl
	 * @return
	 */
	public static String doGet(String httpurl) {
		HttpURLConnection connection = null;
		InputStream is = null;
		BufferedReader br = null;
		String result = null;// 返回结果字符串
		try {
			// 创建远程url连接对象
			URL url = new URL(httpurl);
			// 通过远程url连接对象打开一个连接，强转成httpURLConnection类
			connection = (HttpURLConnection) url.openConnection();
			// 设置连接方式：get
			connection.setRequestMethod("GET");
			// 设置连接主机服务器的超时时间：15000毫秒
			connection.setConnectTimeout(15000);
			// 设置读取远程返回的数据时间：60000毫秒
			connection.setReadTimeout(60000);
			// 发送请求
			connection.connect();
			// 通过connection连接，获取输入流
			if (connection.getResponseCode() == 200) {
				is = connection.getInputStream();
				// 封装输入流is，并指定字符集
				br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
				// 存放数据
				StringBuffer sbf = new StringBuffer();
				String temp = null;
				while ((temp = br.readLine()) != null) {
					sbf.append(temp);
					sbf.append("\r\n");
				}
				result = sbf.toString();
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 关闭资源
			if (null != br) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (null != is) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			connection.disconnect();// 关闭远程连接
		}

		return result;
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 * 
	 * @param url
	 *            发送请求的 URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param) {
		OutputStream out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");//解决乱码
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setConnectTimeout(3000);
			out = conn.getOutputStream();
			out.write(param.getBytes("UTF-8"));
			out.flush();
			int code = conn.getResponseCode();
			MessageLogger.error("返回的response信息" + conn.getResponseMessage());
			MessageLogger.error("返回的code" + code);
			if (code == 200) {
				in = new BufferedReader(
						new InputStreamReader(conn.getInputStream(),"UTF-8"));
				String line;

				while ((line = in.readLine()) != null) {
					result += line + "\n";
				}
			}
		} catch (Exception e) {
			result="请求http失败"+e.getMessage();
			MessageLogger.error("请求http失败"+e.getMessage());
		}
		//使用finally块来关闭输出流、输入流
		finally{
			try{
				if(out!=null){
					out.close();
				}
				if(in!=null){
					in.close();
				}
			}
			catch(IOException ex){
				result="请求http失败"+ex.getMessage();
				ex.printStackTrace();
			}
		}
		return result;
	} 
	
	/**
	 * 向指定 URL 带head发送POST方法的请求
	 *
	 * @param url
	 *            发送请求的 URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendHeadPost(String url, String param,Map<String, String> heads) {
		OutputStream out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");//解决乱码
			if(heads!=null && heads.size()>0){
				for(String key: heads.keySet()){
					String value=heads.get(key);
					conn.setRequestProperty(key, value);
				}
			}
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setConnectTimeout(3000);
			out = conn.getOutputStream();
			out.write(param.getBytes("UTF-8"));
			out.flush();
			int code = conn.getResponseCode();
			if (code == 200) {
				in = new BufferedReader(
						new InputStreamReader(conn.getInputStream(),"UTF-8"));
				String line;

				while ((line = in.readLine()) != null) {
					result += line + "\n";
				}
			}
		} catch (Exception e) {
			result="请求http失败"+e.getMessage();
		}
		//使用finally块来关闭输出流、输入流
		finally{
			try{
				if(out!=null){
					out.close();
				}
				if(in!=null){
					in.close();
				}
			}
			catch(IOException ex){
				result="请求http失败"+ex.getMessage();
				ex.printStackTrace();
			}
		}
		return result;
	}
	
	
	  /**
               * 此方法仅供参考，第三方系统可采用自己的方式调用http接口【OA消息发送的http】
     *
     * @param path 请求路径
     * @param data 请求参数
     * @return
     */
    public static String oapost(String path, Map<String, String> params, Map<String, String> data) {
        try {
            String str = "";
//            if (params != null) {
//                StringBuilder stringBuilder = new StringBuilder("?");
//                for (Map.Entry<String, String> entry : params.entrySet()) {
//                    stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
//                }
//                if (stringBuilder.length() > 1)
//                    path += stringBuilder.substring(0, stringBuilder.length() - 1);
//            }
            URL url = new URL(path);
            //打开和url之间的连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//            PrintWriter out = null;
            // 请求参数 编码为 utf-8
            //请求方式
            conn.setRequestMethod("POST");
            //设置通用的请求属性
            conn.setConnectTimeout(3000);
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            if (data != null)
                for (Map.Entry<String, String> entry : data.entrySet())
                    conn.setRequestProperty(entry.getKey(), entry.getValue());
            //设置是否向httpUrlConnection输出，设置是否从httpUrlConnection读入，此外发送post请求必须设置这两个
            //最常用的Http请求无非是get和post，get请求可以获取静态页面，也可以把参数放在URL字串后面，传递给servlet，
            //post与get的 不同之处在于post的参数不是放在URL字串里面，而是放在http请求的正文内。
            conn.setDoOutput(true);
            conn.setDoInput(true);
            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
            if (params != null)
                out.write(mapToStr(params));
            //缓冲数据
            out.flush();
            out.close();
            //获取URLConnection对象对应的输入流
            InputStream is = conn.getInputStream();
            //构造一个字符流缓存
            BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));
            String result = "";
            while ((str = br.readLine()) != null) {
                result = str;
            }
            //关闭流
            is.close();
            //断开连接，最好写上，disconnect是在底层tcp socket链接空闲时才切断。如果正在被其他线程使用就不切断。
            //固定多线程的话，如果不disconnect，链接会增多，直到收发不出信息。写上disconnect后正常一些。
            conn.disconnect();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
             * 将Map转换成字符串参数，用于POST GET 请求
     *
     * @param map
     * @return
     */
    public static String mapToStr(Map<String, String> map) {
        StringBuilder stringBuilder = new StringBuilder();
        if (map != null) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                stringBuilder.append(entry.getKey());
                if (entry.getValue() != null)
                    stringBuilder.append("=").append(entry.getValue());
                stringBuilder.append("&");
            }
        }
        if (stringBuilder.length() > 0)
            return stringBuilder.substring(0, stringBuilder.length() - 1);
        return null;
    }
    
	
	/**
	 *
	 * post请求，支持https请求
	 * @param url   需要请求的网关路径
	 * @param sendData  请求时需要传入的参数
	 * @param urlencode url的编码格式
	 * @param connTimeOut   链接超时时间
	 * @param readTimeOut   读取超时时间
	 * @param contentType   请求头部  固定输入"application/x-www-form-urlencoded;charset="+urlencode
	 * @param header     输入null
	 * @return
	 */
	public static String sendAndRcvHttpPostBase(String url,String sendData,String urlencode,int connTimeOut,int readTimeOut,String contentType,Map<String,String> header){
		Long curTime = System.currentTimeMillis();
		String result = "";
		BufferedReader in = null;
		DataOutputStream out = null;
		int code = 999;
		HttpsURLConnection httpsConn = null;
		HttpURLConnection httpConn = null;
		try{
			URL myURL = new URL(url);
			if(url.startsWith("https://")){
				httpsConn =    (HttpsURLConnection) myURL.openConnection();
				TrustManager[] trustAllCerts = new TrustManager[]{
						new X509TrustManager() {
							public java.security.cert.X509Certificate[] getAcceptedIssuers() {
								return null;
							}
							public void checkClientTrusted(
									java.security.cert.X509Certificate[] certs, String authType) {
							}
							public void checkServerTrusted(
									java.security.cert.X509Certificate[] certs, String authType) {
							}
						}
				};
				SSLContext sc = SSLContext.getInstance("TLS");
				sc.init(null, trustAllCerts, new java.security.SecureRandom());
				httpsConn.setSSLSocketFactory(sc.getSocketFactory());
				HostnameVerifier hv = new HostnameVerifier() {
					@Override
					public boolean verify(String urlHostName, SSLSession session) {
						return true;
					}
				};
				httpsConn.setHostnameVerifier(hv);
				httpsConn.setRequestProperty("Accept-Charset", urlencode);
				httpsConn.setRequestProperty("User-Agent","java HttpsURLConnection");
				if(header!=null){
					for(String key:header.keySet()){
						httpsConn.setRequestProperty(key, (String)header.get(key));
					}
				}
				httpsConn.setRequestMethod("POST");
				httpsConn.setUseCaches(false);
				httpsConn.setConnectTimeout(3000);
				httpsConn.setRequestProperty("Content-Type",contentType);
				httpsConn.setConnectTimeout(connTimeOut);
				httpsConn.setReadTimeout(readTimeOut);
				httpsConn.setDoInput(true);
				httpsConn.setInstanceFollowRedirects(true);
				if(sendData !=null){
					httpsConn.setDoOutput(true);
					// 获取URLConnection对象对应的输出流
					out = new DataOutputStream(httpsConn.getOutputStream());
					// 发送请求参数
					out.write(sendData.getBytes(urlencode));
					// flush输出流的缓冲
					out.flush();
					out.close();
				}
				// 取得该连接的输入流，以读取响应内容
				in = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(),urlencode));
				code = httpsConn.getResponseCode();
			}else{
				httpConn =    (HttpURLConnection) myURL.openConnection();
				httpConn.setRequestProperty("Accept-Charset", urlencode);
				httpConn.setRequestProperty("user-agent","java HttpURLConnection");
				if(header!=null){
					for(String key:header.keySet()){
						httpConn.setRequestProperty(key, (String)header.get(key));
					}
				}
				httpConn.setRequestMethod("POST");
				httpConn.setUseCaches(false);
				httpConn.setRequestProperty("Content-Type",contentType);
				httpConn.setConnectTimeout(connTimeOut);
				httpConn.setReadTimeout(readTimeOut);
				httpConn.setDoInput(true);
				httpConn.setInstanceFollowRedirects(true);
				if(sendData !=null){
					httpConn.setDoOutput(true);
					// 获取URLConnection对象对应的输出流
					out = new DataOutputStream(httpConn.getOutputStream());
					// 发送请求参数
					out.write(sendData.getBytes(urlencode));
					// flush输出流的缓冲
					out.flush();
					out.close();
				}
				// 取得该连接的输入流，以读取响应内容
				in = new BufferedReader(new InputStreamReader(httpConn.getInputStream(),urlencode));
				code = httpConn.getResponseCode();
			}
			if (HttpURLConnection.HTTP_OK == code){
				String line;
				while ((line = in.readLine()) != null) {
					result += line;
					System.out.println("=====返回结果====="+ line);
				}
				if(result.length()>2000){
					MessageLogger.error( "http返回结果 !\n"+result.substring(0,2000)+"...");
				}else{
					MessageLogger.error( "http返回结果 !\n"+result);
				}
			}else{
				result = null;
				MessageLogger.error("发送代办失败,服务端响应码："+code);
				throw new Exception("发送代办失败,服务端响应码："+code);
			}
		}catch(IOException e){
			MessageLogger.error( "http通讯失败 !"+e.getMessage());
			result = null;
		}catch(Exception e){
			MessageLogger.error("http通讯失败 !"+e.getMessage());
			result = null;
		}finally{
			MessageLogger.error("对方地址："+url);
			if(out!=null){
				try {
					out.close();
				} catch (IOException e) {
					MessageLogger.error("关闭流失败："+e.getMessage());
				}
			}
			if(httpConn!=null){
				httpConn.disconnect();
			}
			if(httpsConn!=null){
				httpsConn.disconnect();
			}
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {
				}
			}
		}
		MessageLogger.error( "SimpleHttpConnUtil "+curTime+" end for "+(System.currentTimeMillis()-curTime)+"ms");
		return result;
	}

	/**
	 * get请求，支持https请求
	 * @param url   需要请求的网关路径
	 * @param sendData  请求时需要传入的参数
	 * @param urlencode url的编码格式
	 * @param connTimeOut   链接超时时间
	 * @param readTimeOut   读取超时时间
	 * @param contentType   请求头部  固定输入"application/x-www-form-urlencoded;charset="+urlencode
	 * @param header     输入null
	 * @return
	 */
	public static String sendAndRcvHttpGettBase(String url,String sendData,String urlencode){
		Long curTime = System.currentTimeMillis();
		String result = "";
		BufferedReader in = null;
		DataOutputStream out = null;
		int code = 999;
		HttpsURLConnection httpsConn = null;
		HttpURLConnection httpConn = null;
		try{
			URL myURL = new URL(url);
			if(url.startsWith("https://")){
				httpsConn =    (HttpsURLConnection) myURL.openConnection();
				TrustManager[] trustAllCerts = new TrustManager[]{
						new X509TrustManager() {
							public java.security.cert.X509Certificate[] getAcceptedIssuers() {
								return null;
							}
							public void checkClientTrusted(
									java.security.cert.X509Certificate[] certs, String authType) {
							}
							public void checkServerTrusted(
									java.security.cert.X509Certificate[] certs, String authType) {
							}
						}
				};
				SSLContext sc = SSLContext.getInstance("TLS");
				sc.init(null, trustAllCerts, new java.security.SecureRandom());
				httpsConn.setSSLSocketFactory(sc.getSocketFactory());
				HostnameVerifier hv = new HostnameVerifier() {
					@Override
					public boolean verify(String urlHostName, SSLSession session) {
						return true;
					}
				};
				httpsConn.setRequestMethod("GET");
				httpsConn.setConnectTimeout(5000);
				httpsConn.setReadTimeout(5000);
				httpsConn.setDoOutput(true);
				// 发送请求
				httpsConn.connect();
				// 取得该连接的输入流，以读取响应内容
				in = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(),urlencode));
				code = httpsConn.getResponseCode();
			}
			if (HttpURLConnection.HTTP_OK == code){
				String line;
				while ((line = in.readLine()) != null) {
					result += line;
					System.out.println("=====返回结果====="+ line);
				}
				if(result.length()>2000){
					MessageLogger.error( "http返回结果 !\n"+result.substring(0,2000)+"...");
				}else{
					MessageLogger.error( "http返回结果 !\n"+result);
				}
			}else{
				result = null;
				MessageLogger.error("创建代办失败,服务端响应码："+code);
				throw new Exception("创建代办失败,服务端响应码："+code);
			}
		}catch(IOException e){
			MessageLogger.error( "http通讯失败 !"+e.getMessage());
			result = null;
		}catch(Exception e){
			MessageLogger.error("http通讯失败 !"+e.getMessage());
			result = null;
		}finally{
			MessageLogger.error("对方地址："+url);
			if(out!=null){
				try {
					out.close();
				} catch (IOException e) {
					MessageLogger.error("关闭流失败："+e.getMessage());
				}
			}
			if(httpConn!=null){
				httpConn.disconnect();
			}
			if(httpsConn!=null){
				httpsConn.disconnect();
			}
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {
				}
			}
		}
		MessageLogger.error( "SimpleHttpConnUtil "+curTime+" end for "+(System.currentTimeMillis()-curTime)+"ms");
		return result;
	}
}
